本文介绍一下怎么通过 Native 代码使用 Java Binder Service。
接下来我们演示使用 Cpp 代码访问 Binder 程序示例之 java 篇 (opens new window) 编写的 Java Binder Service。
在 device/jelly/rice14
目录下创建如下的文件与文件夹:
NativeCallJavaServiceSimple/
├── Android.bp
└── CppClient.cpp
2
3
其中 CppClient.cpp 内容如下: ····················
#define LOG_TAG "aidl_cpp"
#include <log/log.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <android/log.h>
#include <errno.h>
#include <binder/IServiceManager.h>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <private/binder/binder_module.h>
#include <string.h>
#include <cutils/properties.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include <stdarg.h>
#include <stdlib.h>
using namespace android;
int main(void)
{
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> ibinder = sm->getService(String16("hello"));
Parcel data,reply;
if(ibinder != NULL)
{
static String16 descriptor = String16("com.yuandaima.IHelloService");
data.writeInterfaceToken(descriptor);
//data.writeString16(String16("client from Native"));
ibinder->transact(IBinder::FIRST_CALL_TRANSACTION + 0, data, &reply, 0);
int result = reply.readInt32();
ALOGI("transact result : %d\n", result);
return 0;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
主要分为 4 步执行:
- 获得 Hello 服务,与 Java 程序区别是这里不做转换了,直接使用 IBinder(实际类型是 BpBinder)
- 构建好两个 Parcel 结构,data reply
- 通过 BpBinder 的 transact 方法发起远程调用
- 处理返回的 reply
接着我们在系统源码下执行:
source build/envsetup.sh
lunch
make installclean
2
3
然后终端进入到 device/jelly/rice14/NativeCallJavaServiceSimple
,编译我们的源码:
mm
接着我们进入 device/jelly/rice14/BinderJavaDemo
目录下,编译 C++ 服务端:
mm
接着回到系统源码目录下,push 源码产物到 Android 模拟器上:
adb push out/target/product/rice14/system/bin/CppClient /data/local/tmp
adb push out/target/product/rice14/system/framework/BinderServer.jar /data/local/tmp
2
接着进入 Andorid shell,执行程序:
adb shell
cd /data/local/tmp
# 执行服务端
export CLASSPATH=/data/local/tmp/BinderServer.jar
app_process /data/local/tmp com.yuandaima.Server &
# 执行客户端
./CppClient
2
3
4
5
6
7
最后查看log:
logcat | grep "aidl_cpp"
从 log 中看出 Client 收到了回复的数据 0,证明我们的调用成功了。
以上介绍的方法算是一种简易的零时解决方案,更为完整的做法是利用 aidl 生成的文件来“衔接” Java 层和 C++ 层:
首先在 device/jelly/rice14
目录下创建如下的文件与文件夹:
NativeCallJavaService/
├── Android.bp
└── CppClient.cpp
2
3
我们把 device/jelly/rice14/BinderJavaDemo/com/yuandaima/IHelloService.aidl
文件拷贝到 device/jelly/rice14/NativeCallJavaService/com/yuandaima
,接着我们在终端中进入 device/jelly/rice14/NativeCallJavaService
目录,接着使用 aidl 生成代码:
aidl-cpp com/yuandaima/IHelloService.aidl ./ ./IHelloService.cpp
然后修改源码:
package com.yuandaima;
import android.util.Log;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.Parcel;
public class JavaClient {
public static final String TAG = "JavaClient";
public static void main(String[] args) {
//获取Native Binder Service的代理
IBinder binder = ServiceManager.getService("IHello");
String DESCRIPTOR = "com.yuandaima.IHello";
IHello svr = IHello.Stub.asInterface(binder);
try {
svr.hello();
Log.i(TAG, "call hello");
} catch (Exception e) {
}
try {
int cnt = svr.sum(3, 4);
Log.i(TAG, "call sum(3, 4)");
} catch (Exception e) {
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
然后修改编译文件 Android.bp:
cc_binary {
name: "CppClient",
srcs: ["CppClient.cpp", "IHelloService.cpp"],
shared_libs: [
"liblog",
"libcutils",
"libutils",
"libbinder",
],
}
2
3
4
5
6
7
8
9
10
11
接着在 device/jelly/rice14/NativeCallJavaService
目录下单编模块:
mm
最后我们来测试一下:
adb push out/target/product/rice14/system/bin/CppClient /data/local/tmp
# 进入 Android shell 环境
adb shell
cd /data/local/tmp
export CLASSPATH=/data/local/tmp/BinderServer.jar
app_process /data/local/tmp com.yuandaima.Server &
./CppClient
2
3
4
5
6
7
8
接着查看 log:
logcat | grep HelloService
08-07 14:34:54.086 1636 1636 I SystemServer: JavaHelloService
08-07 14:34:54.089 1636 1636 D SystemServerTiming: JavaHelloService took to complete: 3ms
08-08 18:10:42.498 6029 6039 I HelloService: sayhello : cnt = 1
08-08 18:10:42.499 6029 6039 I HelloService: sayhello_to nihao : cnt = 1
2
3
4
5
从 Log 可以看出我们的 Native 客户端已经成功访问到 Java Binder 服务了。